home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 7
/
Aminet 7 - August 1995.iso
/
Aminet
/
comm
/
net
/
AmiPOP116.lha
/
AmiPOP116
/
source
/
pop_dopop.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-11
|
11KB
|
621 lines
#include "pop.h"
/* Stuff for "From " Header */
/* Courtesy Michael B. Smith */
struct mytm {
int year;
int month;
int day;
int dow;
int hour;
int min;
int sec;
};
/* DaysInMonth */
static const int dim [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static const char *months [] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static const char *days [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static void DateStampToMyTm (struct DateStamp *date, struct mytm *da)
{
int days, years, leap = 0, month = 0;
days = date->ds_Days + 731; /* 1976 */
years = days / (365*3+366); /* #quad yrs */
days -= years * (365*3+366);
years = 1976 + 4 * years;
if (days <= 365)
{
leap = 1;
}
else
{
days -= 366;
++years;
years += days / 365;
days %= 365;
}
month = 0;
while (1)
{
if (month == 1)
{
if (days < (28 + leap)) break;
days -= 28 + leap;
}
else
{
if (days < dim [month]) break;
days -= dim [month];
}
++month;
}
da->hour = date->ds_Minute / 60;
da->min = date->ds_Minute % 60;
da->sec = date->ds_Tick / 50;
da->day = days + 1;
da->month = month + 1;
da->dow = date->ds_Days % 7; /* 0 = sunday */
da->year = years;
return;
}
char * datestr (char *buf)
{
/*
** datestr
**
** Build ARPA date-time as specified in RFC-822:
**
** Wed, 13 Oct 93 18:52:04 EST
** 123456789012345678901234567890
**
** buf must be 24 characters, plus space for TimeZone and NUL.
**
** As TimeZone may be "(+23:30)" or similar, 33 chars should
** do it.
*/
struct mytm da;
struct DateStamp ds;
DateStampToMyTm (DateStamp (&ds), &da);
DoFmt (buf, "%s, %ld %s %ld %02ld:%02ld:%02ld",
days [da.dow], da.day,
months [da.month - 1], da.year % 100,
da.hour, da.min, da.sec);
return buf;
}
char * time_stamp (char *buf)
{
/*
** time_stamp
**
** Put a time/date stamp into buf (for logging)
**
** 13 Nov 93 13:14:45
*/
struct DateStamp ds;
struct mytm da;
DateStampToMyTm (DateStamp (&ds), &da);
DoFmt (buf, "%ld %s %ld %02ld:%02ld:%02ld",
da.day,
months [da.month - 1], da.year % 100,
da.hour, da.min, da.sec);
return buf;
}
/* End stuff for "From " header */
#define ASYNCBUFSIZE 8192
BOOL needfrom ( char * , struct AsyncFile *);
/* Variables global to this file */
struct Library *SockBase ;
int havemail;
/* Functions */
int dopop(void)
{
int s;
int count=1;
int okay=1;
struct hostent *hp;
struct sockaddr_in sa;
DoFmt(title,"Connecting to %s",pophost);
settitle(title);
if((SockBase = OpenLibrary( SOCKLIBNAME, SOCKLIBVERSION )) == NULL)
{
doreq("Error opening "SOCKLIBNAME"\n",bum);
return(1);
}
#ifdef AMITCP
SetErrnoPtr(&errno, sizeof errno);
#else
setup_sockets( MAXSOCKS, &errno );
#endif
if((hp=gethostbyname(pophost))==NULL)
{
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
doreq("Connection Refused.",bum);
return(1);
}
bzero(&sa, sizeof(sa));
bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons((u_short)port);
if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
{
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
doreq("Something bad\nhas happened.",bum);
return(1);
}
if (connect(s,(struct sockaddr *) &sa,sizeof(sa))< 0)
{
doreq("No POP3 daemon\nrunning on this\nmachine or port.",bum);
s_close(s);
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
return(1);
}
/* Put actual code here */
/* We need to loop on this recv, because the initial greeting may not fit in one BUFSIZE.
We loop until we get a "\n" */
settitle("Got Connection");
recv(s,buf,BUFSIZE-1,0);
while (!(strstr(buf,"\n")))
{
recv(s,buf,BUFSIZE-1,0);
}
if (senduser(s))
{
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
return(1);
}
havemail=sendstat(s);
while ((okay) && ((havemail > count) || (havemail == count)))
{
DoFmt(title,"Retrieving %lu of %lu",count,havemail);
settitle(title);
okay=retrieve(s,count);
if (delmail && okay)
{
DoFmt(title,"Deleting %lu",count);
settitle(title);
okay=delmessage(s,count);
}
++count;
}
if(sendquit(s))
{
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
return(1);
}
if (Project0Wnd)
{
SetWindowTitles(Project0Wnd,Project0Wdt, (UBYTE *) ~0);
}
if (havemail && notify) /* removed sendstat() after Nofify */
{
doreq("You have new mail.","Cool");
}
/* End actual code */
s_close(s);
#ifndef AMITCP
cleanup_sockets();
#endif
CloseLibrary( SockBase ) ;
return(0);
}
int senduser(int s)
{
int t;
settitle("Sending Username");
DoFmt(buf,"USER %s\r\n",username);
if ( !trans(s,buf) ) return(1);
t=sscanf(buf,"%s",temp);
if ( valcheck(t,temp) ) return(1);
/* Password */
if (password[1])
{
settitle("Sending Password");
DoFmt(buf,"PASS %s\r\n",password);
if ( !trans(s,buf) ) return(1);
t=sscanf(buf,"%s",temp);
if ( valcheck(t,temp) ) return(1);
}
return(0);
}
int sendquit(int s)
{
int t;
settitle("Sending QUIT");
DoFmt(buf,"QUIT\r\n");
if ( !trans(s,buf) ) return(1);
t=sscanf(buf,"%s",temp);
if ( valcheck(t,temp) ) return(1);
settitle("Quit Acknowledged");
return(0);
}
int sendstat( int s )
{
int t;
int count=0;
DoFmt(buf,"STAT\r\n");
if ( !trans(s,buf) ) return(0);
t=sscanf(buf,"%s %lu",temp,&count);
if ( valcheck(t,temp) ) return(0);
return(count);
}
/* function retrieve does the work of retrieving a message, removing
the byte stuffing and writing it to the mailfile.
Rewritten by David Duggan, Sandia National Labs */
int retrieve(int s, int count)
{
int foo; /* temp integer for numb bytes read */
int state; /* flag saying what state we are in */
int x1; /* index for tmpbuf */
char *tmpbuf; /* ptr to place to put unstuffed msg */
char *buf3; /* ptr to front of mail message */
char *buf4; /* ptr to char being examined in mail message */
struct AsyncFile *ofp;
if ( ! (tmpbuf = AllocVec(BUFSIZE,MEMF_CLEAR)))
{
doreq("Not enough memory for buffer.",bum);
return(0);
}
if (( count == 1 ) && ( !appfile ))
{
ofp = OpenAsync(mailbox, MODE_WRITE,ASYNCBUFSIZE);
}
else
{
ofp = OpenAsync(mailbox, MODE_APPEND,ASYNCBUFSIZE);
}
if ( ofp == NULL )
{
doreq("Unable to lock Mailbox.\nCheck path and filename.",bum);
FreeVec(tmpbuf);
return(0);
}
DoFmt(buf,"RETR %lu\r\n",count);
if ( !trans(s,buf) ) /* send data, get answer */
{
CloseAsync(ofp);
FreeVec(tmpbuf);
return(0);
}
if ( valcheck(1,buf) ) /* check for good response */
{
CloseAsync(ofp);
FreeVec(tmpbuf);
return(0);
}
/* Here we have a good first line for this multi-line response.
Now we should process the rest of the buffer */
buf3 = strstr(buf,"\r\n");
if (buf3 != NULL) buf3 += 2;/* move ptr past first line */
needfrom(buf3,ofp); /* add "from" if needed */
buf4 = buf3 = strip(buf3); /* remove CRs */
state = 0; /* start clean every time */
while ( state < 3 )
{
x1 = 0; /* reset index */
while ( *buf4 ) /* until we hit the end of buffer */
{
switch (state)
{
case 0:
if ( *buf4 == '\n' )
{
state++; /* go to next state */
}
tmpbuf[x1++] = *buf4;/* move character */
break;
case 1:
if ( *buf4 == '.' )
{
state++; /* next state, deleting period */
}
else
{ /* reset state if not "\n" */
if (*buf4 != '\n')
{
state = 0;
}
tmpbuf[x1++] = *buf4;/* move character */
}
break;
case 2:
if ( *buf4 == '\n' )
{
state++; /* go to final state */
}
else
{
state = 0; /* reset the state */
}
tmpbuf[x1++] = *buf4;
break;
} /* switch */
buf4++; /* move to next byte */
}
tmpbuf[x1] = '\0'; /* terminate it */
if ( state < 3 ) /* we need more in the buffer */
{
if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf) ) == -1)
{
doreq("Error writing to mailbox.",bum);
CloseAsync(ofp);
FreeVec(tmpbuf);
return(0); /* return error */
}
/* get next buffer full */
foo = recv(s,buf,(BUFSIZE - 1),0);
if ( foo > 0 )
{
buf[foo] = '\0'; /* terminate it for grins */
buf4 = buf3 = strip(buf);/* remove CRs */
}
else
{ /* should never happen! */
doreq("Internal Error.",bum);
state = 4;/* should never happen */
}
} /* if (state < 3) */
} /* while (state < 3) */
/* write out last buffer, leaving off last ".\n" */
if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf)) == -1 )
{
doreq("Error writing to Mailbox.",bum);
CloseAsync(ofp);
FreeVec(tmpbuf);
return(0); /* return error */
}
CloseAsync(ofp);
FreeVec(tmpbuf);
return(1);
} /* end of retrieve */
int delmessage( int s, int count )
{
DoFmt(buf,"DELE %lu\r\n",count);
trans(s,buf);
if ( valcheck(1,buf) ) return(0);
return(1);
}
int valcheck(int t, char *localtemp)
{
if (t == 0)
{
doreq("Got a bogus return string.",bum);
return(1);
}
if ( !strstr(localtemp,"+OK") )
{
doreq("Didn't get +OK",bum);
if (localtemp[0] != '\0')
{
doreq(localtemp,bum);
}
return(1);
}
return(0);
}
int trans( int s, char *mybuf )
{
int foo;
send(s,mybuf,strlen(mybuf),0);
bzero(buf,BUFSIZE);
foo=recv(s,buf,BUFSIZE-1,0);
if ( foo < 1 )
{
return(0);
}
buf[foo]='\0';
return (1);
}
void settitle( char *newtitle )
{
if (winop)
{
SetWindowTitles(Project0Wnd,newtitle, (UBYTE *) ~0);
}
}
/* Scott, this is a slight modification of your strip. It has the exact same
functionality as yours, except it uses dynamic memory instead of the stack
for the temporary buffer. If you want to leave your routine here,
everything should work just the same. David */
/* function strip will strip out all the carraige returns
from the buffer and return the original pointer */
char * strip( char *mybuf )
{
char tmpbuf[BUFSIZE];
ULONG x1, x2, len;
len = strlen(mybuf);
/* strip out the CRs */
for (x1 = x2 = 0 ; x1 < len; x1++)
{
tmpbuf[x2] = mybuf[x1];
if ( tmpbuf[x2] != '\r' ) x2++;
}
tmpbuf[x2] = '\0'; /* terminate it */
strcpy(mybuf,tmpbuf); /* copy back the string */
return(mybuf); /* return their buf ptr */
} /* end of strip */
int lastblock (char *segment)
{
char *found;
int len = strlen(segment);
if ( (found=strstr(segment,"\r\n.\r\n")))
{
/*buf[found-segment]='\n';*/
buf[found-segment]='\0'; /* used to be found-segment+2 */
return(0);
}
if ( (len==2) && (found=strstr(segment,"\r\n")) )
{
buf[found-segment]='\0'; /* Added recently */
return(0);
}
if ( len==1 ) /* Kludge of the century */
{
return(0);
}
if ( (len <= 4) && (found=strstr(segment,".\r\n")) )
{
/*buf[found-segment]='\n';*/
buf[found-segment]='\0';
return(0);
}
return(1);
}
BOOL needfrom(char *mybuf,struct AsyncFile *ofp)
{
if ( !strstr(mybuf,"From ") )
{
char *newtemp;
if (newtemp=AllocVec(BIGSTRING,MEMF_CLEAR))
{
int tempsize=0;
DoFmt(newtemp,"From %s@%s ", username,pophost);
tempsize=strlen(newtemp);
DoFmt((newtemp+tempsize),"%s\n",datestr((newtemp+tempsize)));
WriteAsync(ofp,newtemp,strlen(newtemp));
FreeVec(newtemp);
}
return(TRUE);
}
return(FALSE);
}